home *** CD-ROM | disk | FTP | other *** search
/ CICA 1995 September (Japanese) / CICA Shareware for Windows CD-ROM (Walnut Creek) (September 1995) (Japanese) (Disc 2).iso / disc2 / nt / ntperf.exe / PERFTOOLS / SRC / PERFMON / UTILS.C_ / UTILS.C
Encoding:
C/C++ Source or Header  |  1993-06-05  |  42.2 KB  |  1,590 lines

  1. /*
  2. ==============================================================================
  3.  
  4.   Application:
  5.  
  6.             Microsoft Windows NT (TM) Performance Monitor
  7.  
  8.   File:
  9.             utils.c -- miscellaneous utility routines.  
  10.  
  11.             This file contains miscellaneous utiltity routines, mostly 
  12.             low-level windows helpers. These routines are not specific
  13.             to the perfmon utillity.
  14.  
  15.   Copyright 1992, Microsoft Corporation. All Rights Reserved.
  16.   Microsoft Confidential.
  17. ==============================================================================
  18. */
  19.  
  20.  
  21. //==========================================================================//
  22. //                                  Includes                                //
  23. //==========================================================================//
  24.  
  25.  
  26.  
  27. #include <stdarg.h>  // For ANSI variable args. Dont use UNIX <varargs.h>
  28. #include <stdlib.h>  // For itoa
  29. #include <stdio.h>   // for vsprintf.
  30. #include <string.h>  // for strtok
  31.  
  32. #include "perfmon.h"
  33. #include "pmemory.h"        // for MemoryXXX (mallloc-type) routines
  34. #include "utils.h"
  35. #include "pmhelpid.h"       // IDs for WinHelp
  36.  
  37. //==========================================================================//
  38. //                                  Constants                               //
  39. //==========================================================================//
  40.  
  41.  
  42. #define DOS_FILES                0x0000   // Ordinary files
  43. #define DOS_READONLY             0x0001   // Read-only files
  44. #define DOS_HIDDEN               0x0002   // Hidden files
  45. #define DOS_SYSTEM               0x0004   // System files
  46. #define DOS_SUBDIRECTORIES       0x0010   // Subdirectories
  47. #define DOS_ARCHIVES             0x0020   // Archives
  48. #define DOS_LIB_DIR              0x2000   // LB_DIR flag
  49. #define DOS_DRIVES               0x4000   // Drives
  50. #define DOS_EXCLUSIVE            0x8000   // Exclusive bit
  51. #define DOS_DRIVES_DIRECTORIES   0xC010   // Find drives and directories only
  52.  
  53.  
  54. #define WILD_ONE                 '?'
  55. #define WILD_ANY                 '*'
  56.  
  57.  
  58.  
  59.  
  60. //==========================================================================//
  61. //                              Local Functions                             //
  62. //==========================================================================//
  63.  
  64.  
  65.  
  66. void ClientRectToScreen (HWND hWnd,
  67.                          LPRECT lpRect)
  68. /*
  69.    Effect:        Remaps lpRect from client coordinates to screen
  70.                   coordinates. Analogous to ClientToScreen for rectangles.
  71.  
  72.    Note:          To convert a rectangle from the client coordinates of
  73.                   Wnd1 to the client coordinates of Wnd2, call:
  74.  
  75.                         ClientRectToScreen (hWnd1, &rect) ;
  76.                         ScreenRectToClient (hWnd2, &rect) ;
  77.  
  78.    See Also:      ClientToScreen (windows), ScreenRectToClient.
  79.  
  80.    Internals:     Since a rectangle is really only two points, let
  81.                   windows do the work with ClientToScreen.
  82. */
  83.    {  /* ClientRectToScreen */
  84.    POINT    pt1, pt2 ;
  85.  
  86.    pt1.x = lpRect->left ;
  87.    pt1.y = lpRect->top ;
  88.  
  89.    pt2.x = lpRect->right ;
  90.    pt2.y = lpRect->bottom ;
  91.  
  92.    ClientToScreen (hWnd, &pt1) ;
  93.    ClientToScreen (hWnd, &pt2) ;
  94.  
  95.    lpRect->left = pt1.x ;
  96.    lpRect->top = pt1.y ;
  97.  
  98.    lpRect->right = pt2.x ;
  99.    lpRect->bottom = pt2.y ;
  100.    }  // ClientRectToScreen
  101.  
  102.  
  103. void ScreenRectToClient (HWND hWnd, LPRECT lpRect)
  104. /*
  105.    Effect:        Remaps lpRect from screen coordinates to client
  106.                   coordinates. Analogous to ScreenToClient for rectangles.
  107.  
  108.    Note:          To convert a rectangle from the client coordinates of
  109.                   Wnd1 to the client coordinates of Wnd2, call:
  110.  
  111.                         ClientRectToScreen (hWnd1, &rect) ;
  112.                         ScreenRectToClient (hWnd2, &rect) ;
  113.  
  114.    See Also:      ScreenToClient (windows), ClientRectToScreen.
  115.  
  116.    Internals:     Since a rectangle is really only two points, let
  117.                   windows do the work with ScreenToClient.
  118. */
  119.    {  // ScreenRectToClient
  120.    POINT    pt1, pt2 ;
  121.  
  122.    pt1.x = lpRect->left ;
  123.    pt1.y = lpRect->top ;
  124.  
  125.    pt2.x = lpRect->right ;
  126.    pt2.y = lpRect->bottom ;
  127.  
  128.    ScreenToClient (hWnd, &pt1) ;
  129.    ScreenToClient (hWnd, &pt2) ;
  130.  
  131.    lpRect->left = pt1.x ;
  132.    lpRect->top = pt1.y ;
  133.  
  134.    lpRect->right = pt2.x ;
  135.    lpRect->bottom = pt2.y ;
  136.    }  // ScreenRectToClient
  137.  
  138.  
  139. //==========================================================================//
  140. //                             Exported Functions                           //
  141. //==========================================================================//
  142.  
  143.  
  144. void Line (HDC hDC,
  145.            HPEN hPen,
  146.            int x1, int y1,
  147.            int x2, int y2)
  148.    {  // Line
  149.    HPEN           hPenPrevious ;
  150.  
  151.    if (hPen)
  152.       hPenPrevious = SelectPen (hDC, hPen) ;
  153.    MoveToEx (hDC, x1, y1, NULL) ;
  154.    LineTo (hDC, x2, y2) ;
  155.    if (hPen)
  156.       SelectObject (hDC, hPenPrevious) ;
  157.    }  // Line
  158.  
  159. #if 0
  160. void HLine (HDC hDC,
  161.             HPEN hPen,
  162.             int x1, 
  163.             int x2, 
  164.             int y)
  165.    {  // HLine
  166.    Line (hDC, hPen, x1, y, x2, y) ;
  167.    }
  168.  
  169.  
  170. void VLine (HDC hDC,
  171.             HPEN hPen,
  172.             int x,
  173.             int y1,
  174.             int y2)
  175.    {  // VLine
  176.    Line (hDC, hPen, x, y1, x, y2) ;
  177.    }  // VLine
  178. #endif
  179.  
  180. #ifdef  KEEP_UTIL
  181. void Fill (HDC hDC,
  182.            DWORD rgbColor,
  183.            LPRECT lpRect)
  184.    {  // Fill
  185.    HBRUSH         hBrush ;
  186.  
  187.    hBrush = CreateSolidBrush (rgbColor) ;
  188.  
  189.    FillRect (hDC, lpRect, hBrush) ;
  190.  
  191.    DeleteBrush (hBrush) ;
  192.    }  // Fill
  193.  
  194. void ThreeDConvex (HDC hDC,
  195.                int x1, int y1, 
  196.                int x2, int y2)
  197.    {  // ThreeDConvex
  198.    HBRUSH         hBrushPrevious ;
  199.    POINT          aPoints [8] ;
  200.    DWORD          aCounts [2] ;
  201.    HPEN           hPenPrevious ;
  202.  
  203.  
  204.    //┌────────────────────────────┐
  205.    //│ Draw Face                  │
  206.    //└────────────────────────────┘
  207.  
  208.    hBrushPrevious = SelectBrush (hDC, hBrushFace) ;
  209.    PatBlt (hDC, 
  210.            x1 + ThreeDPad, y1 + ThreeDPad, 
  211.            x2 - x1 - ThreeDPad, y2 - y1 - ThreeDPad, 
  212.            PATCOPY) ;
  213.    SelectBrush (hDC, hBrushPrevious) ;
  214.  
  215.    //┌────────────────────────────┐
  216.    //│ Draw Highlight             │
  217.    //└────────────────────────────┘
  218.  
  219.    if (hPenHighlight)
  220.       hPenPrevious = SelectPen (hDC, hPenHighlight) ;
  221.  
  222.    aPoints [0].x = x1 ;
  223.    aPoints [0].y = y2 - 1 ;   // this works slightly diff. than Line ??
  224.    aPoints [1].x = x1 ;
  225.    aPoints [1].y = y1 ;
  226.    aPoints [2].x = x2 ;
  227.    aPoints [2].y = y1 ;
  228.  
  229.    aPoints [3].x = x1 + 1 ;
  230.    aPoints [3].y = y2 - 1 ;
  231.    aPoints [4].x = x1 + 1 ;
  232.    aPoints [4].y = y1 + 1 ;
  233.    aPoints [5].x = x2 - 1 ;
  234.    aPoints [5].y = y1 + 1 ;
  235.  
  236.    aCounts [0] = 3 ;
  237.    aCounts [1] = 3 ;
  238.  
  239.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  240.    
  241.    
  242.    if (hPenHighlight)
  243.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  244.  
  245. //   HLine (hDC, hPenHighlight, x1, x2, y1) ;              // outside top line
  246. //   HLine (hDC, hPenHighlight, x1 + 1, x2 - 1, y1 + 1) ;  // inside top line
  247. //   VLine (hDC, hPenHighlight, x1, y1, y2) ;              // outside left line
  248. //   VLine (hDC, hPenHighlight, x1 + 1, y1 + 1, y2 - 1) ;  // inside left line
  249.  
  250.    //┌────────────────────────────┐
  251.    //│ Draw Shadow                │
  252.    //└────────────────────────────┘
  253.  
  254.    if (hPenShadow)
  255.       hPenPrevious = SelectPen (hDC, hPenShadow) ;
  256.  
  257.    aPoints [0].x = x1 + 1 ;
  258.    aPoints [0].y = y2 - 1 ;
  259.    aPoints [1].x = x2 ;
  260.    aPoints [1].y = y2 - 1 ;
  261.    aPoints [2].x = x2 ;
  262.    aPoints [2].y = y2 - 2 ;
  263.    aPoints [3].x = x1 + 2 ;
  264.    aPoints [3].y = y2 - 2 ;
  265.  
  266.    aPoints [4].x = x2 - 1 ;
  267.    aPoints [4].y = y1 ;
  268.    aPoints [5].x = x2 - 1 ;
  269.    aPoints [5].y = y2 - 1;
  270.    aPoints [6].x = x2 - 2 ;
  271.    aPoints [6].y = y2 - 1 ;
  272.    aPoints [7].x = x2 - 2 ;
  273.    aPoints [7].y = y1 ;
  274.  
  275.    aCounts [0] = 4 ;
  276.    aCounts [1] = 4 ;
  277.  
  278.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  279.    
  280.    
  281.    if (hPenShadow)
  282.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  283.  
  284. //   HLine (hDC, hPenShadow, x1 + 1, x2, y2 - 1) ;   // outside bottom line
  285. //   HLine (hDC, hPenShadow, x1 + 2, x2, y2 - 2) ;   // inside bottom line
  286. //   VLine (hDC, hPenShadow, x2 - 1, y1 + 1, y2) ;   // outside right line
  287. //   VLine (hDC, hPenShadow, x2 - 2, y1 + 2, y2) ;   // inside right line
  288.  
  289.    }  // ThreeDConvex
  290.  
  291.  
  292.  
  293. void ThreeDConcave (HDC hDC,
  294.                     int x1, int y1, 
  295.                     int x2, int y2,
  296.                     BOOL bFace)
  297.    {  // ThreeDConcave
  298.    HBRUSH         hBrushPrevious ;
  299.    POINT          aPoints [6] ;
  300.    DWORD          aCounts [2] ;
  301.    HPEN           hPenPrevious ;
  302.  
  303.  
  304.    //┌────────────────────────────┐
  305.    //│ Draw Face                  │
  306.    //└────────────────────────────┘
  307.  
  308.    if (bFace)
  309.       {
  310.       hBrushPrevious = SelectBrush (hDC, hBrushFace) ;
  311.       PatBlt (hDC, 
  312.               x1 + ThreeDPad, y1 + ThreeDPad, 
  313.               x2 - x1 - ThreeDPad, y2 - y1 - ThreeDPad, 
  314.               PATCOPY) ;
  315.       SelectBrush (hDC, hBrushPrevious) ;
  316.       }
  317.  
  318.    //┌────────────────────────────┐
  319.    //│ Draw Shadow                │
  320.    //└────────────────────────────┘
  321.  
  322. #if 1
  323.    if (hPenShadow)
  324.       hPenPrevious = SelectPen (hDC, hPenShadow) ;
  325.  
  326.    aPoints [0].x = x1 ;
  327.    aPoints [0].y = y2 - 1 ;
  328.    aPoints [1].x = x1 ;
  329.    aPoints [1].y = y1 ;
  330.    aPoints [2].x = x2 ;
  331.    aPoints [2].y = y1 ;
  332.  
  333.    aPoints [3].x = x1 + 1 ;
  334.    aPoints [3].y = y2 - 1 ;
  335.    aPoints [4].x = x1 + 1 ;
  336.    aPoints [4].y = y1 + 1 ;
  337.    aPoints [5].x = x2 - 1 ;
  338.    aPoints [5].y = y1 + 1 ;
  339.  
  340.    aCounts [0] = 3 ;
  341.    aCounts [1] = 3 ;
  342.  
  343.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  344.    
  345.    if (hPenShadow)
  346.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  347.  
  348. #else
  349.    HLine (hDC, hPenShadow, x1, x2, y1) ;              // outside top line
  350.    HLine (hDC, hPenShadow, x1 + 1, x2 - 1, y1 + 1) ;  // inside top line
  351.    VLine (hDC, hPenShadow, x1, y1, y2) ;              // outside left line
  352.    VLine (hDC, hPenShadow, x1 + 1, y1 + 1, y2 - 1) ;  // inside left line
  353. #endif
  354.  
  355.    //┌────────────────────────────┐
  356.    //│ Draw Highlight             │
  357.    //└────────────────────────────┘
  358.  
  359. #if 1
  360.    if (hPenHighlight)
  361.       hPenPrevious = SelectPen (hDC, hPenHighlight) ;
  362.  
  363.    aPoints [0].x = x1 + 1 ;
  364.    aPoints [0].y = y2 - 1 ;
  365.    aPoints [1].x = x2 ;
  366.    aPoints [1].y = y2 - 1 ;
  367.  
  368.    aPoints [2].x = x2 - 1 ;
  369.    aPoints [2].y = y2 - 1 ;
  370.    aPoints [3].x = x2 - 1 ;
  371.    aPoints [3].y = y1 ;
  372.  
  373.    aCounts [0] = 2 ;
  374.    aCounts [1] = 2 ;
  375.  
  376.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  377.    
  378.    if (hPenHighlight)
  379.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  380.  
  381. #else
  382.    HLine (hDC, hPenHighlight, x1 + 1, x2, y2 - 1) ;   // outside bottom line
  383.    VLine (hDC, hPenHighlight, x2 - 1, y1 + 1, y2) ;   // outside right line
  384. #endif   
  385.    }  // ThreeDConcave
  386. #endif // KEEP_UTIL
  387.  
  388.      
  389. void ThreeDConvex1 (HDC hDC,
  390.                     int x1, int y1, 
  391.                     int x2, int y2)
  392.    {  // ThreeDConvex1
  393.    HBRUSH         hBrushPrevious ;
  394.    POINT          aPoints [6] ;
  395.    DWORD          aCounts [2] ;
  396.    HPEN           hPenPrevious ;
  397.  
  398.  
  399.    //┌────────────────────────────┐
  400.    //│ Draw Face                  │
  401.    //└────────────────────────────┘
  402. #if 1
  403.    hBrushPrevious = SelectBrush (hDC, hBrushFace) ;
  404.    PatBlt (hDC, 
  405.            x1 + 1, y1 + 1, 
  406.            x2 - x1 - 1, y2 - y1 - 1, 
  407.            PATCOPY) ;
  408.    SelectBrush (hDC, hBrushPrevious) ;
  409.  
  410.    //┌────────────────────────────┐
  411.    //│ Draw Highlight             │
  412.    //└────────────────────────────┘
  413.  
  414.    if (hPenHighlight)
  415.       hPenPrevious = SelectPen (hDC, hPenHighlight) ;
  416.  
  417.    aPoints [0].x = x1 ;
  418.    aPoints [0].y = y2 - 1 ;
  419.    aPoints [1].x = x1 ;
  420.    aPoints [1].y = y1 ;
  421.    aPoints [2].x = x2 ;
  422.    aPoints [2].y = y1 ;
  423.  
  424.    Polyline (hDC, aPoints, 3) ;
  425.    
  426.    if (hPenHighlight)
  427.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  428.  
  429. #else
  430.    HLine (hDC, hPenHighlight, x1, x2, y1) ;              // outside top line
  431.    VLine (hDC, hPenHighlight, x1, y1, y2) ;              // outside left line
  432. #endif
  433.  
  434.    //┌────────────────────────────┐
  435.    //│ Draw Shadow                │
  436.    //└────────────────────────────┘
  437.  
  438. #if 1
  439.    if (hPenShadow)
  440.       hPenPrevious = SelectPen (hDC, hPenShadow) ;
  441.  
  442.    aPoints [0].x = x1 + 1 ;
  443.    aPoints [0].y = y2 - 1 ;
  444.    aPoints [1].x = x2 ;
  445.    aPoints [1].y = y2 - 1 ;
  446.  
  447.    aPoints [2].x = x2 - 1 ;
  448.    aPoints [2].y = y2 - 1 ;
  449.    aPoints [3].x = x2 - 1 ;
  450.    aPoints [3].y = y1 ;
  451.  
  452.    aCounts [0] = 2 ;
  453.    aCounts [1] = 2 ;
  454.  
  455.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  456.    
  457.    if (hPenShadow)
  458.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  459. #else
  460.    HLine (hDC, hPenShadow, x1 + 1, x2, y2 - 1) ;   // outside bottom line
  461.    VLine (hDC, hPenShadow, x2 - 1, y1 + 1, y2) ;   // outside right line
  462. #endif
  463.  
  464.    }  // ThreeDConvex1
  465.  
  466.  
  467.  
  468. void ThreeDConcave1 (HDC hDC,
  469.                      int x1, int y1, 
  470.                      int x2, int y2)
  471.    {  // ThreeDConcave1
  472.    HBRUSH         hBrushPrevious ;
  473.    POINT          aPoints [6] ;
  474.    DWORD          aCounts [2] ;
  475.    HPEN           hPenPrevious ;
  476.  
  477.  
  478.    //┌────────────────────────────┐
  479.    //│ Draw Face                  │
  480.    //└────────────────────────────┘
  481.  
  482.    hBrushPrevious = SelectBrush (hDC, hBrushFace) ;
  483.    PatBlt (hDC, 
  484.            x1 + 1, y1 + 1, 
  485.            x2 - x1 - 1, y2 - y1 - 1, 
  486.            PATCOPY) ;
  487.    SelectBrush (hDC, hBrushPrevious) ;
  488.  
  489.    //┌────────────────────────────┐
  490.    //│ Draw Shadow                │
  491.    //└────────────────────────────┘
  492.  
  493. #if 1
  494.    if (hPenShadow)
  495.       hPenPrevious = SelectPen (hDC, hPenShadow) ;
  496.  
  497.    aPoints [0].x = x1 ;
  498.    aPoints [0].y = y2 - 1 ;
  499.    aPoints [1].x = x1 ;
  500.    aPoints [1].y = y1 ;
  501.    aPoints [2].x = x2 ;
  502.    aPoints [2].y = y1 ;
  503.  
  504.    Polyline (hDC, aPoints, 3) ;
  505.    
  506.    if (hPenShadow)
  507.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  508. #else
  509.    HLine (hDC, hPenShadow, x1, x2, y1) ;              // outside top line
  510.    VLine (hDC, hPenShadow, x1, y1, y2) ;              // outside left line
  511. #endif
  512.  
  513.    //┌────────────────────────────┐
  514.    //│ Draw Highlight             │
  515.    //└────────────────────────────┘
  516. #if 1
  517.    if (hPenHighlight)
  518.       hPenPrevious = SelectPen (hDC, hPenHighlight) ;
  519.  
  520.    aPoints [0].x = x1 + 1 ;
  521.    aPoints [0].y = y2 - 1 ;
  522.    aPoints [1].x = x2 ;
  523.    aPoints [1].y = y2 - 1 ;
  524.  
  525.    aPoints [2].x = x2 - 1 ;
  526.    aPoints [2].y = y2 - 2 ;
  527.    aPoints [3].x = x2 - 1 ;
  528.    aPoints [3].y = y1 ;
  529.  
  530.    aCounts [0] = 2 ;
  531.    aCounts [1] = 2 ;
  532.  
  533.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  534.    
  535.    if (hPenHighlight)
  536.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  537. #else
  538.    HLine (hDC, hPenHighlight, x1 + 1, x2, y2 - 1) ;   // outside bottom line
  539.    VLine (hDC, hPenHighlight, x2 - 1, y1 + 1, y2) ;   // outside right line
  540. #endif
  541.    
  542.    }  // ThreeDConcave1
  543.  
  544.  
  545. int TextWidth (HDC hDC, LPTSTR lpszText)
  546.    {
  547.    SIZE           size ;
  548.  
  549.    if (!lpszText)
  550.       return (0) ;
  551.  
  552.    GetTextExtentPoint (hDC, lpszText, lstrlen (lpszText), &size) ;
  553.    return  (size.cx) ;
  554.    }
  555.  
  556.  
  557. int _cdecl DlgErrorBox (HWND hDlg, UINT id, ...)
  558.    {
  559.    TCHAR          szMessageFmt [FilePathLen + 1] ;
  560.    TCHAR          szBuffer [FilePathLen * 2] ;
  561.    va_list        vaList ;
  562.    int            NumOfChar ;
  563.    TCHAR          szApplication [WindowCaptionLen] ;
  564.  
  565.    NumOfChar = StringLoad (id, szMessageFmt) ;
  566.  
  567.    if (NumOfChar)
  568.       {
  569.       va_start (vaList, id) ;
  570.       wvsprintf (szBuffer, szMessageFmt, vaList) ;
  571.       va_end (vaList) ;
  572.  
  573.       StringLoad (IDS_APPNAME, szApplication) ;
  574.  
  575.       MessageBox (hDlg, szBuffer, szApplication,
  576.          MB_OK | MB_ICONSTOP | MB_TASKMODAL) ;
  577.       }
  578.  
  579.    return (0) ;
  580.    }
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587. int FontHeight (HDC hDC, 
  588.                  BOOL bIncludeLeading)
  589.    {  // FontHeight
  590.    TEXTMETRIC     tm ;
  591.  
  592.    GetTextMetrics (hDC, &tm) ;
  593.    if (bIncludeLeading)
  594.       return (tm.tmHeight + tm.tmExternalLeading) ;
  595.    else
  596.       return (tm.tmHeight) ;
  597.    }  // FontHeight
  598.  
  599.  
  600.  
  601. int TextAvgWidth (HDC hDC,
  602.                   int iNumChars)
  603.    {
  604.    TEXTMETRIC     tm ;
  605.    int            xAvgWidth ;
  606.  
  607.    GetTextMetrics (hDC, &tm) ;
  608.  
  609.    xAvgWidth = iNumChars * tm.tmAveCharWidth ;
  610.  
  611.    // add 10% slop
  612.    return (MulDiv (xAvgWidth, 11, 10)) ;   
  613.    }
  614.  
  615.  
  616. void WindowCenter (HWND hWnd)
  617. /*
  618.    Effect:        Center the window hWnd in the center of the screen.
  619.                   Physically update the windows appearance as well.
  620.  
  621.    Globals:       xScreenWidth, yScreenHeight.
  622. */
  623.    {  // WindowCenter
  624.    RECT           rectWindow ;
  625.    int            xWindowWidth, yWindowHeight ;
  626.  
  627.    GetWindowRect (hWnd, &rectWindow) ;
  628.    xWindowWidth = rectWindow.right - rectWindow.left ;
  629.    yWindowHeight = rectWindow.bottom - rectWindow.top ;
  630.  
  631.    MoveWindow (hWnd,
  632.                (xScreenWidth - xWindowWidth) / 2,
  633.                (yScreenHeight - yWindowHeight) / 2,
  634.                xWindowWidth,
  635.                yWindowHeight,
  636.                TRUE) ;
  637.    }  // WindowCenter
  638.  
  639.  
  640.  
  641. BOOL DialogMove (HDLG hDlg,
  642.                  WORD wControlID,
  643.                  int xPos, 
  644.                  int yPos,
  645.                  int xWidth,
  646.                  int yHeight)
  647. /*
  648.    Effect:        Move the control identified by wControlID in the dialog  
  649.                   hDlg to the new position (xPos, yPos), and resize to
  650.                   (xWidth, yHeight). If any of these values are NOCHANGE, retain
  651.                   the current value.
  652.  
  653.    Examples:      DialogMove (hDlg, IDD_FOO, 10, 20, NOCHANGE, NOCHANGE)
  654.                      moves control but does not resize it
  655.  
  656.                   DialogMove (hDlg, IDD_FOO, NOCHANGE, NOCHANGE, 100, NOCHANGE)
  657.                      sets width of control to 100
  658. */                     
  659.    {  // DialogMove
  660.    HWND        hWndControl ;
  661.    RECT        rectControl ;
  662.  
  663.    hWndControl = DialogControl (hDlg, wControlID) ;
  664.    if (!hWndControl)
  665.       return (FALSE) ;
  666.    GetWindowRect (hWndControl, &rectControl) ;
  667.    ScreenRectToClient (hDlg, &rectControl) ;
  668.  
  669.    MoveWindow (hWndControl,
  670.                (xPos == NOCHANGE) ? rectControl.left : xPos,
  671.                (yPos == NOCHANGE) ? rectControl.top : yPos,
  672.                (xWidth == NOCHANGE) ? rectControl.right - rectControl.left : xWidth,
  673.                (yHeight == NOCHANGE) ? rectControl.bottom - rectControl.top : yHeight,
  674.                TRUE) ;
  675.  
  676.    return (TRUE) ;
  677.    }  // DialogMove
  678.  
  679.  
  680. int DialogWidth (HDLG hDlg, 
  681.                  WORD wControlID)
  682.    {
  683.    HWND           hWndControl ;
  684.    RECT           rectControl ;
  685.  
  686.    hWndControl = DialogControl (hDlg, wControlID) ;
  687.    if (!hWndControl)
  688.       return (0) ;
  689.  
  690.    GetWindowRect (hWndControl, &rectControl) ;
  691.    return (rectControl.right - rectControl.left) ;
  692.    }
  693.    
  694.  
  695. int DialogHeight (HDLG hDlg, 
  696.                   WORD wControlID)
  697.    {
  698.    HWND           hWndControl ;
  699.    RECT           rectControl ;
  700.  
  701.    hWndControl = DialogControl (hDlg, wControlID) ;
  702.    if (!hWndControl)
  703.       return (0) ;
  704.  
  705.    GetWindowRect (hWndControl, &rectControl) ;
  706.    return (rectControl.bottom - rectControl.top) ;
  707.    }
  708.    
  709.  
  710. int DialogXPos (HDLG hDlg,
  711.                 WORD wControlID)
  712.    {  // DialogXPos
  713.    HWND           hWndControl ;
  714.    RECT           rectControl ;
  715.  
  716.    hWndControl = DialogControl (hDlg, wControlID) ;
  717.    if (!hWndControl)
  718.       return (0) ;
  719.  
  720.    GetWindowRect (hWndControl, &rectControl) ;
  721.    ScreenRectToClient (hDlg, &rectControl) ;
  722.  
  723.    return  (rectControl.left) ;
  724.    }  // DialogXPos
  725.  
  726.  
  727. int DialogYPos (HDLG hDlg,
  728.                 WORD wControlID)
  729.    {  // DialogYPos
  730.    HWND           hWndControl ;
  731.    RECT           rectControl ;
  732.  
  733.    hWndControl = DialogControl (hDlg, wControlID) ;
  734.    if (!hWndControl)
  735.       return (0) ;
  736.  
  737.    GetWindowRect (hWndControl, &rectControl) ;
  738.    ScreenRectToClient (hDlg, &rectControl) ;
  739.  
  740.    return  (rectControl.top) ;
  741.    }  // DialogYPos
  742.  
  743.  
  744. void DialogEnable (HDLG hDlg,
  745.                    WORD wID,
  746.                    BOOL bEnable)
  747. /*
  748.    Effect:        Enable or disable (based on bEnable) the control 
  749.                   identified by wID in dialog hDlg.
  750.  
  751.    See Also:      DialogShow.
  752. */
  753.    {  // DialogEnable
  754.    HCONTROL       hControl ;
  755.  
  756.    hControl = GetDlgItem (hDlg, wID) ;
  757.    if (hControl)
  758.       EnableWindow (hControl, bEnable) ;
  759.    }  // DialogEnable
  760.  
  761.  
  762. void DialogShow (HDLG hDlg,
  763.                  WORD wID,
  764.                  BOOL bShow)
  765.    {  // DialogShow
  766.    HCONTROL       hControl ;
  767.  
  768.    hControl = GetDlgItem (hDlg, wID) ;
  769.    if (hControl)
  770.       ShowWindow (hControl, bShow ? SW_SHOW : SW_HIDE) ;
  771.    }  // DialogShow
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778. BOOL _cdecl DialogSetText (HDLG hDlg,
  779.                            WORD wControlID,
  780.                            WORD wStringID,
  781.                            ...)
  782.    {  // DialogSetText
  783.    TCHAR           szFormat [ControlStringLen] ;
  784.    TCHAR           szText [ControlStringLen] ;
  785.    va_list         vaList ;
  786.  
  787.    if (LoadString (hInstance, wStringID,
  788.                    szFormat, ControlStringLen - 1))
  789.       {
  790.       va_start (vaList, wStringID) ;
  791.       wvsprintf (szText, szFormat, vaList) ;
  792.       va_end (vaList) ;
  793.  
  794.       SetDlgItemText (hDlg, wControlID, szText) ;
  795.       return (TRUE) ;
  796.       }  // if
  797.    else
  798.       return (FALSE) ;
  799.    }  // DialogSetText
  800.  
  801.  
  802. BOOL _cdecl DialogSetString (HDLG hDlg,
  803.                              WORD wControlID,
  804.                              LPTSTR lpszFormat,
  805.                              ...)
  806.    {  // DialogSetString
  807.    TCHAR          szText [ControlStringLen] ;
  808.    va_list        vaList ;
  809.  
  810.    va_start (vaList, lpszFormat) ;
  811.    wvsprintf (szText, lpszFormat, vaList) ;
  812.    va_end (vaList) ;
  813.  
  814.    SetDlgItemText (hDlg, wControlID, szText) ;
  815.    return (TRUE) ;
  816.    }  // DialogSetString
  817.  
  818.  
  819.  
  820. LPTSTR LongToCommaString (LONG lNumber,
  821.                           LPTSTR lpszText)
  822.    {  // LongToCommaString
  823.    BOOL           bNegative ;
  824.    TCHAR          szTemp1 [40] ;
  825.    TCHAR          szTemp2 [40] ;
  826.    LPTSTR         lpsz1 ;
  827.    LPTSTR         lpsz2 ;
  828.    int            i ;
  829.    int            iDigit ;
  830.  
  831.    // 1. Convert the number to a reversed string.
  832.    lpsz1 = szTemp1 ;
  833.    bNegative = (lNumber < 0) ;
  834.    lNumber = labs (lNumber) ;
  835.  
  836.    if (lNumber)
  837.       while (lNumber)
  838.          {
  839.          iDigit = (int) (lNumber % 10L) ;
  840.          lNumber /= 10L ;
  841.          *lpsz1++ = (TCHAR) (TEXT('0') + iDigit) ;
  842.          }
  843.    else
  844.       *lpsz1++ = TEXT('0') ;
  845.    *lpsz1++ = TEXT('\0') ;
  846.  
  847.  
  848.    // 2. reverse the string and add commas
  849.    lpsz1 = szTemp1 + lstrlen (szTemp1) - 1 ;
  850.    lpsz2 = szTemp2 ;
  851.  
  852.    if (bNegative)
  853.       *lpsz2++ = TEXT('-') ;
  854.  
  855.    for (i = lstrlen (szTemp1) - 1;
  856.         i >= 0 ;
  857.         i--)
  858.       {  // for
  859.       *lpsz2++ = *lpsz1-- ;
  860.       if (i && !(i % 3))
  861.          *lpsz2++ = TEXT(',') ;
  862.       }  // for
  863.    *lpsz2++ = TEXT('\0') ;
  864.  
  865.    return (lstrcpy (lpszText, szTemp2)) ;
  866.    }  // LongToCommaString
  867.  
  868.  
  869.  
  870. BOOL MenuSetPopup (HWND hWnd,
  871.                    int iPosition,
  872.                    WORD  wControlID,
  873.                    LPTSTR lpszResourceID)
  874.    {
  875.    HMENU          hMenuMain ;
  876.    HMENU          hMenuPopup ;
  877.    TCHAR          szTopChoice [MenuStringLen + 1] ;
  878.  
  879.    hMenuMain = GetMenu (hWnd) ;
  880.    hMenuPopup = LoadMenu (hInstance, lpszResourceID) ;
  881.  
  882.    if (!hMenuMain || !hMenuPopup)
  883.       return (FALSE) ;
  884.  
  885.    StringLoad (wControlID, szTopChoice) ;
  886.    return (ModifyMenu (hMenuMain, iPosition, MF_BYPOSITION | MF_POPUP,
  887.                        (UINT) hMenuPopup, szTopChoice)) ;
  888.    }               
  889.          
  890.  
  891.    
  892. LPTSTR FileCombine (LPTSTR lpszFileSpec,
  893.                     LPTSTR lpszFileDirectory,
  894.                     LPTSTR lpszFileName)
  895.    {  // FileCombine
  896.  
  897.    int      stringLen ;
  898.    TCHAR    DIRECTORY_DELIMITER[2] ;
  899.  
  900.    DIRECTORY_DELIMITER[0] = TEXT('\\') ;
  901.    DIRECTORY_DELIMITER[1] = TEXT('\0') ;
  902.  
  903.    lstrcpy (lpszFileSpec, lpszFileDirectory) ;
  904.  
  905.    stringLen = lstrlen (lpszFileSpec) ;
  906.    if (stringLen > 0 &&
  907.        lpszFileSpec [stringLen - 1] != DIRECTORY_DELIMITER [0])
  908.       lstrcat (lpszFileSpec, DIRECTORY_DELIMITER) ;
  909.  
  910.    lstrcat (lpszFileSpec, lpszFileName) ;
  911.  
  912.    return (lpszFileSpec) ;
  913.    }  // FileCombine
  914.  
  915. // This routine extract the filename portion from a given full-path filename
  916. LPTSTR ExtractFileName (LPTSTR pFileSpec)
  917.    {
  918.    LPTSTR   pFileName = NULL ;
  919.    TCHAR    DIRECTORY_DELIMITER1 = TEXT('\\') ;
  920.    TCHAR    DIRECTORY_DELIMITER2 = TEXT(':') ;
  921.  
  922.    if (pFileSpec)
  923.       {
  924.       pFileName = pFileSpec + lstrlen (pFileSpec) ;
  925.  
  926.       while (*pFileName != DIRECTORY_DELIMITER1 &&
  927.          *pFileName != DIRECTORY_DELIMITER2)
  928.          {
  929.          if (pFileName == pFileSpec)
  930.             {
  931.             // done when no directory delimiter is found
  932.             break ;
  933.             }
  934.          pFileName-- ;
  935.          }
  936.       
  937.       if (*pFileName == DIRECTORY_DELIMITER1 ||
  938.          *pFileName == DIRECTORY_DELIMITER2)
  939.          {
  940.          // directory delimiter found, point the 
  941.          // filename right after it
  942.          pFileName++ ;
  943.          }
  944.       }
  945.    return pFileName ;
  946.    }  // ExtractFileName
  947.  
  948. int CBAddInt (HWND hWndCB,
  949.               int iValue)
  950.    {  // CBAddInt
  951.    TCHAR       szValue [ShortTextLen + 1] ;
  952.    CHAR        szCharValue [ShortTextLen + 1] ;
  953.  
  954.    itoa (iValue, (LPSTR)szCharValue, 10) ;
  955. #ifdef UNICODE
  956.    mbstowcs (szValue, (LPSTR)szCharValue, strlen((LPSTR)szCharValue)+1) ;
  957.    return (CBAdd (hWndCB, szValue)) ;
  958. #else
  959.    return (CBAdd (hWndCB, szCharValue)) ;
  960. #endif
  961.  
  962.    }  // CBAddInt
  963.  
  964. void DialogSetInterval (HDLG hDlg,
  965.                         WORD wControlID,
  966.                         int  IntervalMSec)
  967.    {
  968.    TCHAR          szValue [MiscTextLen] ;
  969.  
  970.    TSPRINTF (szValue, TEXT("%3.3f"),
  971.             (FLOAT)(IntervalMSec) / (FLOAT)1000.0) ;
  972.  
  973.    SetDlgItemText (hDlg, wControlID, szValue) ;
  974.    }
  975.  
  976. void DialogSetFloat (HDLG hDlg,
  977.                      WORD wControlID,
  978.                      FLOAT eValue)
  979.    {
  980.    TCHAR          szValue [40] ;
  981.    FLOAT          tempValue = eValue ;
  982.  
  983.    if (tempValue < (FLOAT) 0.0)
  984.       {
  985.       tempValue = - tempValue ;
  986.       }
  987.  
  988.    if (tempValue < (FLOAT) 1.0E+8)
  989.       {
  990.       TSPRINTF (szValue, TEXT("%1.4f"), eValue) ;
  991.       }
  992.    else
  993.       {
  994.       TSPRINTF (szValue, TEXT("%14.6e"), eValue) ;
  995.       }
  996.  
  997.    SetDlgItemText (hDlg, wControlID, szValue) ;
  998.    }
  999.  
  1000.  
  1001. FLOAT DialogFloat (HDLG hDlg, 
  1002.                    WORD wControlID,
  1003.                    BOOL *pbOK)
  1004. /*
  1005.    Effect:        Return a floating point representation of the string
  1006.                   value found in the control wControlID of hDlg.
  1007.  
  1008.    Internals:     We use sscanf instead of atof becuase atof returns a 
  1009.                   double. This may or may not be the right thing to do.
  1010. */
  1011.    {  // DialogFloat
  1012.    TCHAR          szValue [ShortTextLen+1] ;
  1013.    FLOAT          eValue ;
  1014.    int            iNumScanned ;
  1015.  
  1016.    DialogText (hDlg, wControlID, szValue) ;   
  1017.    iNumScanned = swscanf (szValue, TEXT("%e"), &eValue) ;
  1018.  
  1019.    if (pbOK)
  1020.       *pbOK = (iNumScanned == 1) ;
  1021.  
  1022.    return (eValue) ;
  1023.    }  // DialogFloat
  1024.  
  1025.  
  1026.  
  1027. LPTSTR StringAllocate (LPTSTR lpszText1)
  1028.    {  // StringAllocate
  1029.    LPTSTR         lpszText2 ;
  1030.  
  1031.    if (!lpszText1)
  1032.       return (NULL) ;
  1033.  
  1034.    if (lstrlen (lpszText1) == 0)
  1035.       return (NULL) ;
  1036.  
  1037.    lpszText2 = MemoryAllocate ((lstrlen (lpszText1)+1) * sizeof (TCHAR)) ;
  1038.    if (lpszText2)
  1039.       lstrcpy (lpszText2, lpszText1) ;
  1040.  
  1041.    return  (lpszText2) ;
  1042.    }  // StringAllocate
  1043.  
  1044.  
  1045.  
  1046. int DivRound (int iNumerator, int iDenominator)
  1047. /*
  1048.    Effect:        Return the quotient (iNumerator / iDenominator).
  1049.                   Round the quotient to the nearest integer.
  1050.                   This function is similar to normal integer division (/),
  1051.                   but normal division always rounds down.
  1052.  
  1053.    Note:          Surely there must already be a runtime version of this,
  1054.                   but I couldn't find it. 
  1055.  
  1056.    Note:          This function originally used the runtime div function
  1057.                   instead of (/ and %), but the div runtime function is
  1058.                   now broken (build 265).   
  1059. */
  1060.    {  // DivRound
  1061.    int            iQuotient ;
  1062.    int            iRemainder ;
  1063.  
  1064.  
  1065.    iQuotient = iNumerator / iDenominator ;
  1066.    iRemainder = iNumerator % iDenominator ;
  1067.  
  1068.    if (iRemainder >= (iDenominator / 2))
  1069.       iQuotient++ ;
  1070.  
  1071.    return (iQuotient) ;
  1072.    }
  1073.  
  1074.  
  1075. BOOL MenuEnableItem (HMENU hMenu,
  1076.                      WORD wID,
  1077.                      BOOL bEnable)
  1078. /*
  1079.    Effect:        Enable or disable, depending on bEnable, the menu item
  1080.                   associated with id wID in the menu hMenu.
  1081.  
  1082.                   Any disabled menu items are displayed grayed out.
  1083.  
  1084.    See Also:      EnableMenuItem (windows).
  1085. */
  1086.    {  // MenuEnableItem
  1087.    return (EnableMenuItem (hMenu, wID,
  1088.                            bEnable ?
  1089.                               (MF_ENABLED | MF_BYCOMMAND) :
  1090.                               (MF_GRAYED | MF_BYCOMMAND))) ;
  1091.    }  // MenuEnableItem
  1092.  
  1093.  
  1094. int BitmapWidth (HBITMAP hBitmap)
  1095.    {  // BitmapWidth
  1096.    BITMAP  bm ;
  1097.  
  1098.    GetObject (hBitmap, sizeof (BITMAP), (LPSTR) &bm) ;
  1099.    return (bm.bmWidth) ;
  1100.    }  // BitmapWidth
  1101.  
  1102.  
  1103. int BitmapHeight (HBITMAP hBitmap)
  1104.    {  // BitmapHeight
  1105.    BITMAP  bm ;
  1106.  
  1107.    GetObject (hBitmap, sizeof (BITMAP), (LPSTR) &bm) ;
  1108.    return (bm.bmHeight) ;
  1109.    }  // BitmapHeight
  1110.  
  1111.  
  1112.  
  1113. int WindowHeight (HWND hWnd)
  1114.    {  // WindowHeight
  1115.    RECT           rectWindow ;
  1116.  
  1117.    GetWindowRect (hWnd, &rectWindow) ;
  1118.    return (rectWindow.bottom - rectWindow.top) ;
  1119.    }  // WindowHeight
  1120.  
  1121.  
  1122.  
  1123. int WindowWidth (HWND hWnd)
  1124.    {  // WindowWidth
  1125.    RECT           rectWindow ;
  1126.  
  1127.    GetWindowRect (hWnd, &rectWindow) ;
  1128.    return (rectWindow.right - rectWindow.left) ;
  1129.    }  // WindowWidth
  1130.  
  1131.  
  1132.  
  1133. void WindowResize (HWND hWnd,
  1134.                    int xWidth,
  1135.                    int yHeight)
  1136. /*
  1137.    Effect:        Change the size of the window hWnd, leaving the
  1138.                   starting position intact.  Redraw the window.
  1139.  
  1140.                   If either xWidth or yHeight is NULL, keep the
  1141.                   corresponding dimension unchanged.
  1142.  
  1143.    Internals:     Since hWnd may be a child of another parent, we need
  1144.                   to scale the MoveWindow arguments to be in the client
  1145.                   coordinates of the parent.
  1146.             
  1147. */
  1148.    {  // WindowResize
  1149.    RECT           rectWindow ;
  1150.    HWND           hWndParent ;
  1151.  
  1152.    GetWindowRect (hWnd, &rectWindow) ;
  1153.    hWndParent = WindowParent (hWnd) ;
  1154.  
  1155.    if (hWndParent)
  1156.       ScreenRectToClient (hWndParent, &rectWindow) ;
  1157.    
  1158.    MoveWindow (hWnd,
  1159.                rectWindow.left,
  1160.                rectWindow.top,
  1161.                xWidth ? xWidth : rectWindow.right - rectWindow.left,
  1162.                yHeight ? yHeight : rectWindow.bottom - rectWindow.top,
  1163.                TRUE) ;
  1164.    }  // WindowResize
  1165.  
  1166.  
  1167.  
  1168.  
  1169. void WindowSetTopmost (HWND hWnd, BOOL bTopmost)
  1170. /*
  1171.    Effect:        Set or clear the "topmost" attribute of hWnd. If a window
  1172.                   is "topmost", it remains ontop of other windows, even ones
  1173.                   that have the focus.
  1174. */
  1175.    {
  1176.    SetWindowPos (hWnd, bTopmost ? HWND_TOPMOST : HWND_NOTOPMOST,
  1177.                  0, 0, 0, 0,
  1178.                  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE) ;
  1179.    }
  1180.  
  1181.  
  1182. void WindowEnableTitle (HWND hWnd, BOOL bTitle)
  1183.    {
  1184.    DWORD          dwStyle ;
  1185.  
  1186.  
  1187.    dwStyle = WindowStyle (hWnd) ;
  1188.    
  1189.    if (bTitle)
  1190.       dwStyle = WS_TILEDWINDOW | dwStyle ;
  1191.    else
  1192.       dwStyle = 
  1193.          dwStyle & 
  1194.          ~ (WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) ;
  1195.  
  1196.    if (!bTitle)
  1197.       SetMenu (hWnd, NULL) ;
  1198.  
  1199.    WindowSetStyle (hWnd, dwStyle) ;
  1200.    SetWindowPos (hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
  1201.                  SWP_NOZORDER | SWP_FRAMECHANGED );
  1202.    }
  1203.  
  1204. // removing the following routines since LINK32 is not doing that for us
  1205. #ifdef  KEEP_UTIL
  1206. int MessageBoxResource (HWND hWndParent,
  1207.                         WORD wTextID,
  1208.                         WORD wTitleID,
  1209.                         UINT uiStyle)
  1210. /*
  1211.    Effect:        Just like MessageBox, but takes the title and format
  1212.                   strings from the resoure. In addition, the format string
  1213.                   is used as a printf style format, combined with the 
  1214.                   additional arguments.
  1215. */
  1216.    {  // MessageBoxResource
  1217.    TCHAR          szText [MessageLen + 1] ;
  1218.    TCHAR          szCaption [WindowCaptionLen + 1] ;
  1219.  
  1220.    StringLoad (wTextID, szText) ;
  1221.    StringLoad (wTitleID, szCaption) ;
  1222.  
  1223.    return (MessageBox (hWndParent, szText, szCaption, uiStyle)) ;
  1224.    }  // MessageBoxResource
  1225.  
  1226.  
  1227. #define WndProcKey   TEXT("OLDWNDPROC")
  1228.  
  1229. FARPROC WindowSetWndProc (HWND hWnd,
  1230.                           HANDLE hInstance,
  1231.                           FARPROC lpfnNewWndProc)
  1232. /*
  1233.    Effect:     Replace the window procedure of hWnd with lpfnNewWndProc.
  1234.                Return the existing window procedure.
  1235.  
  1236.    Note:       For proper subclassing, NewWndProc should pass all
  1237.                unhandled messages to the original wndproc.
  1238.  
  1239.    Called By:  WindowSubclass, WindowUnsubclass.
  1240. */
  1241.    {  // WindowSetWndProc
  1242.    FARPROC     lpfnNewProcInstance ;
  1243.    FARPROC     lpfnOldProc ;
  1244.  
  1245.    lpfnOldProc = (FARPROC) GetWindowLong (hWnd, GWL_WNDPROC) ;
  1246.    lpfnNewProcInstance = MakeProcInstance (lpfnNewWndProc, hInstance) ;
  1247.    SetWindowLong (hWnd, GWL_WNDPROC, (long) lpfnNewProcInstance) ;
  1248.  
  1249.    return (lpfnOldProc) ;
  1250.    }  // WindowSetWndProc
  1251.  
  1252. WNDPROC WindowGetOriginalWndProc (HWND hWnd)
  1253. /*
  1254.    Effect:        Return a far pointer to the "original" wndproc for
  1255.                   hWnd.
  1256.  
  1257.    Assert:        WindowSetOriginalProc was already called on this hWnd.
  1258.  
  1259.    See Also:      WindowSetOriginalWndProc.
  1260. */
  1261.    {  // WindowGetOriginalWndProc
  1262.    return (WNDPROC) GetProp (hWnd, WndProcKey) ;
  1263.    }  // WindowGetOriginalWndProc
  1264.  
  1265.  
  1266. void WindowSetOriginalWndProc (HWND hWnd,
  1267.                                FARPROC lpfnWndProc)
  1268. /*
  1269.    Effect:        Save away a far pointer to the "original" wndproc for
  1270.                   hWnd.
  1271.  
  1272.    See Also:      WindowGetOriginalProc.
  1273. */
  1274.    {  // WindowSetOriginalProc
  1275.    SetProp (hWnd, WndProcKey, (LPSTR) lpfnWndProc) ;
  1276.    }  // WindowSetOriginalProc
  1277.  
  1278.  
  1279. void WindowSubclass (HWND hWnd,
  1280.                      HANDLE hInstance,
  1281.                      FARPROC lpfnNewWndProc)
  1282. /*
  1283.    Effect:        Replace the wndproc for hWnd with lpfnNewWndProc.
  1284.                   Save away a pointer to the original procedure.
  1285.  
  1286.    See Also:      WindowUnsubclass.
  1287. */
  1288.    {  // WindowSubclass
  1289.    FARPROC     lpfnOldWndProc ;
  1290.  
  1291.    lpfnOldWndProc = WindowSetWndProc (hWnd, hInstance, lpfnNewWndProc) ;
  1292.    WindowSetOriginalWndProc (hWnd, lpfnOldWndProc) ;
  1293.    }  // WindowSubclass
  1294.  
  1295.  
  1296. LONG WindowCallOriginalWndProc (HWND hWnd,
  1297.                                 UINT msg,
  1298.                                 WPARAM wParam,
  1299.                                 LPARAM lParam)
  1300.    {
  1301.    WNDPROC        lpfnOriginalWndProc ;
  1302.  
  1303.    lpfnOriginalWndProc = WindowGetOriginalWndProc (hWnd) ;
  1304.    if (lpfnOriginalWndProc)
  1305.       return ((LONG) CallWindowProc (lpfnOriginalWndProc,
  1306.                                      hWnd, msg, wParam, lParam)) ;
  1307.    else return (FALSE) ;
  1308.    }
  1309.  
  1310.  
  1311.  
  1312. LRESULT APIENTRY FocusCtlWndProc (HWND hWnd,
  1313.                                   UINT wMsg,
  1314.                                   WPARAM wParam,
  1315.                                   LPARAM lParam)
  1316.    {  // FocusCtlWndProc
  1317.    BOOL           bCallDefProc ;
  1318.    LRESULT        lReturnValue ;
  1319.  
  1320.  
  1321.    bCallDefProc = TRUE ;
  1322.    lReturnValue = 0L ;
  1323.  
  1324.    switch (wMsg)
  1325.       {  // switch
  1326.       case WM_SETFOCUS:
  1327.          SendMessage (WindowParent (hWnd), 
  1328.                       WM_DLGSETFOCUS, WindowID (hWnd), 0) ;
  1329.          break ;
  1330.  
  1331.  
  1332.       case WM_KILLFOCUS:
  1333.          SendMessage (WindowParent (hWnd), 
  1334.                       WM_DLGKILLFOCUS, WindowID (hWnd), 0) ;
  1335.          break ;
  1336.  
  1337.       default:
  1338.          bCallDefProc = TRUE ;
  1339.       }  // switch
  1340.  
  1341.  
  1342.    if (bCallDefProc)
  1343.       lReturnValue = WindowCallOriginalWndProc (hWnd, wMsg, wParam, lParam) ;
  1344.  
  1345.    return (lReturnValue);
  1346.    }  // FocusWndProc
  1347.  
  1348.  
  1349.  
  1350. BOOL DlgFocus (HDLG hDlg, WORD wControlID)
  1351.    {  // DlgFocus
  1352.    HWND           hWndControl ;
  1353.  
  1354.    hWndControl = DialogControl (hDlg, wControlID) ;
  1355.    if (!hWndControl)
  1356.       return (FALSE) ;
  1357.  
  1358.    WindowSubclass (hWndControl, hInstance, (FARPROC) FocusCtlWndProc) ;
  1359.    return (TRUE) ;
  1360.    }  // DlgFocus
  1361.  
  1362.  
  1363. BOOL DeviceNumColors (HDC hDC)
  1364.    {  // DeviceNumColors
  1365.    int            nPlanes ;
  1366.    int            nBitsPixel ;
  1367.  
  1368.    nPlanes = GetDeviceCaps (hDC, PLANES) ;
  1369.    nBitsPixel = GetDeviceCaps (hDC, BITSPIXEL) ;
  1370.  
  1371.    return (1 << (nPlanes * nBitsPixel)) ;
  1372.    }  // DeviceNumColors
  1373.  
  1374.  
  1375. void DrawBitmap (HDC hDC,
  1376.                  HBITMAP hBitmap,
  1377.                  int xPos,
  1378.                  int yPos,
  1379.                  LONG  lROPCode)
  1380.    {  // DrawBitmap
  1381.    BITMAP  bm ;
  1382.    HDC     hDCMemory ;
  1383.  
  1384.    hDCMemory = CreateCompatibleDC (hDC) ;
  1385.    SelectObject (hDCMemory, hBitmap) ;
  1386.  
  1387.    GetObject (hBitmap, sizeof (BITMAP), (LPSTR) &bm) ;
  1388.  
  1389.    BitBlt (hDC,                     // DC for Destination surface
  1390.            xPos, yPos,              // location in destination surface
  1391.            bm.bmWidth, bm.bmHeight, // dimension of bitmap
  1392.            hDCMemory,               // DC for Source surface
  1393.            0, 0,                    // location in source surface
  1394.            lROPCode) ;              // ROP code
  1395.  
  1396.    DeleteDC (hDCMemory) ;
  1397.    }  // DrawBitmap
  1398.  
  1399.  
  1400. #endif  // KEEP_UTIL
  1401.  
  1402. #ifdef PERFMON_DEBUG
  1403.  
  1404. #define MikeBufferSize         256
  1405.  
  1406.  
  1407. int _cdecl mike (TCHAR *szFormat, ...)
  1408. /*
  1409.    Note:          This function returns a value so that it can more easily
  1410.                   be used in conditional expressions.
  1411. */
  1412.    {  // mike
  1413.    TCHAR          szBuffer [MikeBufferSize] ;
  1414.    va_list        vaList ;
  1415.  
  1416.    va_start (vaList, szFormat) ;
  1417.    wvsprintf (szBuffer, szFormat, vaList) ;
  1418.    va_end (vaList) ;
  1419.  
  1420.    MessageBox (NULL, szBuffer, TEXT("Debug"), MB_OK | MB_TASKMODAL) ;
  1421.    return (0) ;
  1422.    }  // mike
  1423.  
  1424.  
  1425.  
  1426. int _cdecl mike1 (TCHAR *szFormat, ...)
  1427. /*
  1428.    Note:          This function returns a value so that it can more easily
  1429.                   be used in conditional expressions.
  1430. */
  1431.    {  //  mike1
  1432.    TCHAR           szBuffer [MikeBufferSize] ;
  1433.    va_list        vaList ;
  1434.    HDC            hDC ;
  1435.    RECT           rect ;
  1436.   
  1437.    va_start (vaList, szFormat) ;
  1438.    wvsprintf (szBuffer, szFormat, vaList) ;
  1439.    va_end (vaList) ;
  1440.  
  1441.    rect.left = 0 ;
  1442.    rect.right = xScreenWidth ;
  1443.    rect.top = 0 ;
  1444.    rect.bottom = 20 ;
  1445.  
  1446.    hDC = CreateScreenDC () ;
  1447.    ExtTextOut (hDC, 0, 0, ETO_OPAQUE, &rect, 
  1448.                szBuffer, lstrlen (szBuffer), NULL) ;
  1449.    DeleteDC (hDC) ;
  1450.  
  1451.    return (0) ;
  1452.    }  // mike1
  1453.  
  1454. int _cdecl mike2 (TCHAR *szFormat, ...)
  1455. /*
  1456.    Note:          This function returns a value so that it can more easily
  1457.                   be used in conditional expressions.
  1458. */
  1459.    {  //  mike2
  1460.    TCHAR           szBuffer [MikeBufferSize] ;
  1461.    va_list        vaList ;
  1462.   
  1463.    va_start (vaList, szFormat) ;
  1464.    wvsprintf (szBuffer, szFormat, vaList) ;
  1465.    va_end (vaList) ;
  1466.  
  1467.    OutputDebugString (szBuffer) ;
  1468.  
  1469.    return (0) ;
  1470.    }  // mike2
  1471. #endif      // PERFMON_DEBUG
  1472.  
  1473.  
  1474.  
  1475. int inttok (LPSTR lpszText, LPSTR lpszDelimiters)
  1476.    {  // inttok
  1477.  
  1478.    // Inttok only works with LPSTRs because of the atoi & strtok
  1479.    
  1480.    LPSTR   lpszToken ;
  1481.  
  1482.    lpszToken = strtok (lpszText, lpszDelimiters) ;
  1483.  
  1484.    if (lpszToken)
  1485.       return (atoi (lpszToken)) ;
  1486.    else
  1487.       return (0) ;
  1488.    }  // inttok
  1489.  
  1490.  
  1491. void WindowPlacementToString (PWINDOWPLACEMENT pWP, 
  1492.                               LPTSTR lpszText)
  1493.    {
  1494.    TSPRINTF (lpszText, TEXT("%d %d %d %d %d %d %d %d %d"),
  1495.             pWP->showCmd, 
  1496.             pWP->ptMinPosition.x,
  1497.             pWP->ptMinPosition.y,
  1498.             pWP->ptMaxPosition.x,
  1499.             pWP->ptMaxPosition.y,
  1500.             pWP->rcNormalPosition.left,
  1501.             pWP->rcNormalPosition.top,
  1502.             pWP->rcNormalPosition.right,
  1503.             pWP->rcNormalPosition.bottom) ;
  1504.    }
  1505.  
  1506.  
  1507. void StringToWindowPlacement (LPTSTR lpszText,
  1508.                               PWINDOWPLACEMENT pWP)
  1509.    {  // StringToWindowPlacement
  1510.    CHAR  SpaceStr[2];
  1511.    CHAR  LocalText[TEMP_BUF_LEN];  
  1512.       
  1513.  
  1514.    SpaceStr[0] = ' ' ;
  1515.    SpaceStr[1] = '\0' ;
  1516.    
  1517. #ifdef UNICODE
  1518.    // convert the unicode string to char string
  1519.    // so we could use inttok
  1520.    wcstombs (LocalText, lpszText, sizeof(LocalText)) ;
  1521. #else
  1522.    strcpy (LocalText, lpszText) ;
  1523. #endif
  1524.  
  1525.    pWP->length = sizeof (WINDOWPLACEMENT) ;
  1526.    pWP->flags = 0 ;
  1527.    pWP->showCmd = inttok (LocalText, SpaceStr) ;
  1528.    pWP->ptMinPosition.x = inttok (NULL, SpaceStr) ;
  1529.    pWP->ptMinPosition.y = inttok (NULL, SpaceStr) ;
  1530.    pWP->ptMaxPosition.x = inttok (NULL, SpaceStr) ;
  1531.    pWP->ptMaxPosition.y = inttok (NULL, SpaceStr) ;
  1532.    pWP->rcNormalPosition.left = inttok (NULL, SpaceStr) ;
  1533.    pWP->rcNormalPosition.top = inttok (NULL, SpaceStr) ;
  1534.    pWP->rcNormalPosition.right = inttok (NULL, SpaceStr) ;
  1535.    pWP->rcNormalPosition.bottom = inttok (NULL, SpaceStr) ;
  1536.    }  // StringToWindowPlacement
  1537.  
  1538.  
  1539.  
  1540. int LogFontHeight (HDC hDC,
  1541.                    int iPointSize)
  1542. /*
  1543.    Effect:        Return the appropriate pixel height for the lfHeight
  1544.                   field of the LOGFONT structure for the requested point
  1545.                   size. This size depends on the number of pixels per
  1546.                   logical inch of the current display context, hDC.
  1547.  
  1548.    Called By:     Any function which wants to create a particular
  1549.                   point-height font.
  1550. */
  1551.    {  // LogFontHeight
  1552.    return (-MulDiv (iPointSize, GetDeviceCaps (hDC, LOGPIXELSY), 72)) ;
  1553.    }  // LogFontHeight
  1554.  
  1555.  
  1556. // this routine converts the input menu id into help id.
  1557. DWORD MenuIDToHelpID (DWORD MenuID)
  1558.    {
  1559.    DWORD HelpID = 0 ;
  1560.  
  1561.    if (MenuID >= IDM_FIRSTMENUID && MenuID <= IDM_LASTMENUID)
  1562.       {
  1563.       // only special cases...
  1564.       if (MenuID >= IDM_OPTIONSREFRESHNOWCHART &&
  1565.           MenuID <= IDM_OPTIONSREFRESHNOWREPORT)
  1566.          {
  1567.          HelpID = HC_PM_MENU_OPTIONSREFRESHNOW ;
  1568.          }
  1569.       else
  1570.          {
  1571.          HelpID = MenuID - MENUIDTOHELPID ;
  1572.          }
  1573. #ifndef ADVANCED_PERFMON
  1574.       // need to convert these 2 IDs for Perf. Meter
  1575.       if (HelpID == HC_PM_MENU_HELPABOUT)
  1576.          {
  1577.          HelpID = HC_NTPM_MENU_HELPABOUT ;
  1578.          }
  1579.       else if (HelpID == HC_PM_MENU_FILEEXIT)
  1580.          {
  1581.          HelpID = HC_NTPM_MENU_FILEEXIT ;
  1582.          }
  1583. #endif
  1584.       }
  1585.  
  1586.    return (HelpID) ;
  1587.    }
  1588.  
  1589. 
  1590.